/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/

#include "SimWindow.h"

#include "wx/wx.h"
#include "wx/glcanvas.h"
#include "GL/gl.h"
#include "GL/glu.h"
#include "owndebug.h"

#include "mathutils.h"

BEGIN_EVENT_TABLE(CSimCanvas,wxGLCanvas)
  EVT_KEY_DOWN(CSimCanvas::OnKey)
  EVT_SIZE(CSimCanvas::OnSize)
END_EVENT_TABLE()

CSimCanvas::CSimCanvas(wxWindow *ParentWindow, int id, int* attribList)
:wxGLCanvas(ParentWindow,id,attribList)
{
  reset=true;
  z=-20;
  y=5;
  x=0;
  pan=0;
  tilt=0;
}

CSimCanvas::~CSimCanvas()
{
  
}

void CSimCanvas::SetView()
{     
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
  if (reset)
  {
    glMatrixMode(GL_PROJECTION);
    glViewport(0, 0, (GLint)this->GetSize().x, (GLint)this->GetSize().y);
    glLoadIdentity();
    gluPerspective(80,(GLint)this->GetSize().x/(GLint)this->GetSize().y,1,1000);
    reset=false;
  }    
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glRotatef(pan,0,1,0);
  glRotatef(tilt,1,0,0);
  glTranslatef(x,-y,z);
}

void CSimCanvas::OnSize(wxSizeEvent &e)
{
  reset=true;
}

void CSimCanvas::OnKey(wxKeyEvent &e)
{
  int key=e.GetKeyCode();
  switch (key) 
  {
    case WXK_UP : 
    //z++;
      x=x-sin(DegToRad(pan));
      z=z+cos(DegToRad(pan));
      break;
    case WXK_DOWN:
      //z--;
      x=x+sin(DegToRad(pan));
      z=z-cos(DegToRad(pan));
      break;
    case WXK_RIGHT:
      pan=pan+5;
      break;
    case WXK_LEFT:
      pan=pan-5;
      break;
    case WXK_PAGEUP:
      y=y+1;
      break;    
    case WXK_PAGEDOWN:
      y=y-1;
      break;
    case WXK_HOME:
      tilt=tilt-2;
      break;
    case WXK_END:
      tilt=tilt+2;
      break;
  }
}

BEGIN_EVENT_TABLE(CSimWindow,wxFrame)
  
END_EVENT_TABLE()

CSimWindow::CSimWindow()
:wxFrame(NULL,wxID_ANY,_T("j2b2 simulator")),
wxThread(wxTHREAD_DETACHED)
{
  int attribList[]={WX_GL_DOUBLEBUFFER,WX_GL_RGBA,0};
  //GLCanvas=new wxGLCanvas(this,wxID_ANY,attribList);
  GLCanvas=new CSimCanvas(this,wxID_ANY,attribList);
  GLContext=new wxGLContext(GLCanvas);
      
  wxGridSizer *gs=new wxGridSizer(1,1);
  gs->Add(GLCanvas,0, wxEXPAND,0);
  this->SetSizer(gs);
      
  World.SetStepSize(0.010);
    
  wxThread::Create();
  Run();
}
    
CSimWindow::~CSimWindow()
{
  
}
    
void* CSimWindow::Entry()
{
      
  init();
      
  while (!TestDestroy())
  {
    //put simulating here
    simulate();
    Sleep(10);
  }
  return NULL;
}

void CSimWindow::init()
{
  printf("SimWindow INIT GRAPHICS CALLED!\n");
  GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
  GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  GLfloat light_specular[] = { 1.0, 0.0, 0.0, 1.0 };
  GLfloat light_position[] = { 0.0, 15.0, 0.0, 0.0 };
  
  GLCanvas->SetCurrent(*GLContext);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  
  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  
  glClearColor(0.0, 0.0, 0.0, 0.0);
}
    
void CSimWindow::simulate()
{
  GLCanvas->SetCurrent(*GLContext);
  GLCanvas->SetView();
  World.Step();
  World.Draw();
  GLCanvas->SwapBuffers();
}


